package com.woniu.service;

import com.alibaba.fastjson.JSON;
import com.woniu.adapter.UserRepositoryApater;
import com.woniu.exception.UserException;
import com.woniu.inlet.web.command.*;
import com.woniu.inlet.web.fo.UserFo;
import com.woniu.inlet.web.vo.BuyVo;
import com.woniu.outlet.client.RegisterMessageMq;
import com.woniu.outlet.client.RegisterPayMq;
import com.woniu.outlet.client.ReliableMessageServiceClient;
import com.woniu.outlet.client.UserPayMq;
import com.woniu.outlet.mysql.dao.UserDao;
import com.woniu.outlet.mysql.po.User;
import com.woniu.outlet.mysql.po.UserExample;
import com.woniu.service.domain.UserDo;
import com.woniu.utils.AppUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

@Service
@Slf4j
@Transactional(noRollbackFor = UserException.class)//自定义的异常触发数据库回滚
public class UserService implements LoginCommandHandler, RegisterCommandHandler,
        PayCommandHandler, VerifyBalanceCommandHandler {

    @Autowired
    private UserRepositoryApater userRepositoryApater;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ReliableMessageServiceClient reliableMessageServiceClient;

    @Autowired
    private UserDao userDao;


    //登录
    @Override
    public UserDo action(LoginCommand loginCommand) {
        UserDo userDo = new UserDo();
        BeanUtils.copyProperties(loginCommand.getUserFo(), userDo);
        log.debug("登录用户的domain对象是：{}", userDo);

        List<User> users = userRepositoryApater.findByPhoneNum(userDo.getPhonenumber());
        if (users.size() <= 0 || users == null) {
            throw new UserException("账号输入有误");
        }
        if (!users.get(0).getPassword().equals(userDo.getPassword())) {
            throw new UserException("密码输入有误");
        }
        try {
            BeanUtils.copyProperties(users.get(0), userDo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.debug("用户账号密码正确，登陆成功！！");
        return userDo;

    }

    //注册
    @Override
    public void action(RegisterCommand command) {
        UserDo userDo = new UserDo();
        BeanUtils.copyProperties(command.getUserFo(), userDo);
        //查找电话号码是否已经注册过
        List<User> users = userRepositoryApater.findByPhoneNum(userDo.getPhonenumber());
        if (users.size() > 0 && users != null) {
            throw new UserException("该电话号码已经被注册了！！！");
        }
        //补全用户信息
        userDo.setPayCount(5);
        userDo.setAccount(userDo.getPhonenumber());//昵称
        userDo.setHeadImg("/images/default.img");
        userDo.setBandCars(0);
        userDo.setRedPackets(0);
        userDo.setCouponNums(0);
        userDo.setTotalAmount(new BigDecimal("0"));
        userDo.setRestAmount(new BigDecimal("0"));
        userDo.setSignDays(0);
        userDo.setPoints(0);
        userDo.setStatus(0);
        Integer id = userRepositoryApater.register(userDo);
        log.debug("发送的消息用户id是[{}]", id);
        //发消息给mq->促销模块，支付模块
        reliableMessageServiceClient.sendMessage(RegisterMessageMq.EXCHANGE_REGISTER, RegisterMessageMq.ROUTING_KEY, String.valueOf(id));
        reliableMessageServiceClient.sendMessage(RegisterPayMq.EXCHANGE_REGISTER_PAY, RegisterPayMq.ROUTING_KEY, String.valueOf(id));
    }

    //支付-->不针对定投
    @Override
    public boolean payMoney(PayCommand payCommand) throws UserException {
        UserFo userFo = payCommand.getUserFo();
        //比对幂等性token
        String s = stringRedisTemplate.opsForValue().get(userFo.getPayToken());
        log.debug("支付的幂等token为[{}]", s);
        if (s == null) {
            throw new UserException("请勿重复提交！！！");
        }
        UserDo userDo = userRepositoryApater.getById(userFo.getId());

        if (userDo.getPayCount() < 1) {//支付次数不够
            boolean timeDifference = AppUtils.getTimeDifference(userDo.getPayTime());
            if (timeDifference == false) {//false ：小于30分钟
                throw new UserException("您已经支付五次失败，请稍后再试");
            } else {
                //重置次数
                userDo.setPayCount(5);
                userRepositoryApater.updateInfo(userDo);
            }
        }
        //判断密码是否正确
        if (!userDo.getPayPassword().equals(userFo.getPayPassword())) {//密码不正确
            userDo.setPayCount(userDo.getPayCount() - 1);
            userDo.setPayTime(AppUtils.getNowTimeStr());
            userRepositoryApater.updateInfo(userDo);
            log.debug("密码错误后，该用户剩余的支付次数[{}]", userDo.getPayCount());
            throw new UserException("您输入的支付密码有误");
        }
        //密码正确-->判断余额是否足够
        if (userDo.getRestAmount().compareTo(userFo.getPayMoney()) == -1) {
            userDo.setPayCount(5);
            userDo.setPayTime(AppUtils.getNowTimeStr());
            userRepositoryApater.updateInfo(userDo);
            throw new UserException("您的余额已不足，请及时冲值！！1");
        }
        //更新余额
        userDo.setRestAmount(userDo.getRestAmount().subtract(userFo.getPayMoney()));

        userDo.setPayTime(AppUtils.getNowTimeStr());
        userDo.setPayCount(5);
        log.debug("支付成功的userDo对象是：[{}]", userDo);
        userRepositoryApater.updateInfo(userDo);

        //删除幂等性token
        // stringRedisTemplate.delete(s);

        BuyVo buyVo = new BuyVo();
        BeanUtils.copyProperties(userFo, buyVo);
        buyVo.setMoney(userFo.getPayMoney());
        buyVo.setUserId(userFo.getId());

        log.debug("要传给MQ的buyVo对象为：[{}]", buyVo);
        String buyVoStr = JSON.toJSONString(buyVo);

        //发消息给可靠消息服务-->告知订单模块生成订单
        reliableMessageServiceClient.sendMessage(UserPayMq.EXCHANGE_USERPAY, UserPayMq.ROUTING_KEY, buyVoStr);

        return true;
    }

    //定投余额验证
    @Override
    public boolean verifyBalance(VerifyBalanceCommand command) {
        UserDo userDo = userRepositoryApater.getById(command.getId());
        log.debug("查询到用户的余额为：【{}】", userDo.getRestAmount());
        log.debug("需要支付的金额时：【{}】", command.getPayMoney());
        if (userDo.getRestAmount().compareTo(command.getPayMoney()) == -1) {//余额小于支付金额
            return false;
        }
        return true;
    }

    //修改密码
    public void updatePassword(UserFo userFo) {

        //根据id查询用户信息
        UserDo userDo = userRepositoryApater.getById(userFo.getId());
        userDo.setPassword(userFo.getPassword());
        //跟新密码
        userRepositoryApater.updateInfo(userDo);
    }

    //根据用户id查询信息
    public UserDo getById(Integer id) {
        UserDo userDo = userRepositoryApater.getById(id);
        return userDo;
    }

    //用户实名认证
    public void certificated(UserFo userFo) {
        //根据身份证号查找用户
        UserExample example = new UserExample();
        example.or().andIdEqualTo(userFo.getId());
        List<User> users = userRepositoryApater.getByExample(example);
        if (users.get(0).getStatus() == 1) {
            throw new UserException("该用户已经实名认证");
        }

        UserExample example1 = new UserExample();
        example1.or().andIdCardEqualTo(userFo.getIdCard());
        List<User> users1 = userRepositoryApater.getByExample(example1);
        if (!users1.isEmpty()) {
            throw new UserException("该身份证号已被认证");
        }
        //银行卡暂未验证
        users.get(0).setRealName(userFo.getRealName());
        users.get(0).setIdCard(userFo.getIdCard());
        users.get(0).setStatus(1);
        users.get(0).setPayPassword(userFo.getPayPassword());
        userDao.updateByPrimaryKeySelective(users.get(0));
    }

    //验证输入的密码是否正确
    public boolean verifypassword(UserFo userFo) {
        User user = userDao.selectByPrimaryKey(userFo.getId());
        if (user.getPassword().equals(userFo.getPassword()))
            return true;
        else
            return false;
    }

    //验证输入的支付密码是否正确
    public boolean verifyPayPassword(UserFo userFo) {
        User user = userDao.selectByPrimaryKey(userFo.getId());
        if (user.getPayPassword().equals(userFo.getPayPassword()))
            return true;
        else
            return false;
    }

    //修改支付密码
    public void updatePayPassword(UserFo userFo) {
        UserDo userDo = userRepositoryApater.getById(userFo.getId());
        userDo.setPayPassword(userFo.getPayPassword());
        userRepositoryApater.updateInfo(userDo);
    }

    //查询多个用户是否存在
    public boolean isExist(List<Integer> ids) {
        for (Integer id : ids) {
            UserDo byId = userRepositoryApater.getById(id);
            if (byId == null)
                return false;
        }
        return true;
    }
}
